// file: drive/keyboard.c
// autor: jiang xinpeng
// time:2021.8.7
// copyright: (C) by jiangxinpeng,All right are reserved.

#include <arch/cpu.h>
#include <arch/acpi.h>
#include <arch/apic.h>
#include <arch/eflags.h>
#include <arch/config.h>
#include <os/debug.h>
#include <lib/type.h>
#include <lib/string.h>
#include <lib/stddef.h>

uint32_t cpunum = 0;
cpuid_t cpu_list[CPU_NUM_MAX];

void CpuInit()
{
    // init cpu list
    for (int i = 0; i < CPU_NUM_MAX; i++)
    {
        cpu_list[i] = 0;
    }
    // attach all cpu on system
    cpunum = CpuGetAttachList(cpu_list);
    KPrint("[cpu] found cpu num %d\n",cpunum);
}

uint32_t CpuGetAttachList(cpuid_t *list)
{
    uint32_t cpu_count = 0;
    acpi_madt_t *madt = (acpi_madt_t *)AcpiGetMadtBase();
    KPrint("[CPU] found madt base at %x\n", madt);

    uint32_t len = madt->len;
    uint8_t *p = (uint8_t *)madt + sizeof(acpi_madt_t);
    uint8_t *end = (uint8_t *)madt + len;
    // start from first entry after skip header
    //KPrint("[CPU] attach cpu start  from %x-%x len %d\n", p, end, len);
    while (p < end)
    {
        uint8_t type = p[0];
        uint8_t len = p[1];
        uint8_t *data = (uint8_t *)(p + 2);

        if (len == 0)
            break;

        switch (type) // switch entry type
        {
        case MADT_PROCESSOR_LOCAL_APIC: // found local APIC
        {
            //KPrint("[CPU] found entry LOCAL_APIC base %x\n len %x\n", p, len);
            if (*((uint32_t *)(data + 2)) & 1)
            {
                list[cpu_count] = ((madt_processor_localAPIC_t *)data)->APIC_ID;
                //KPrint("Attach CPU ID %d\n", list[cpu_count]);
                cpu_count++; // attach cpu increase count
            }
        }
        break;
        default:
            break;
        }
        p += len; // next entry
    }
    return cpu_count;
}

cpuid_t CpuGetMyId()
{
#ifdef ENABLE_SMP
    // return current cpu
    return APICGetID();
#else
    return (cpuid_t)cpu_list[0];
#endif
}
